package main

import (
	"log"
	"os"

	"gitee.com/general252/gortc/pkg/format"
	"gitee.com/general252/gortc/pkg/rtcsdp"
	"gitee.com/general252/gortc/pkg/rtcsession"
	"github.com/bluenviron/gortsplib/v4/pkg/format/rtph264"
)

func init() {
	log.SetFlags(log.LstdFlags | log.Lshortfile)
}

const overTCP = true

type ObjectClient struct {
}

func NewObjectClient() *ObjectClient {
	c := &ObjectClient{}

	return c
}

func (tis *ObjectClient) offer(overTCP bool) *rtcsdp.Session {
	var offer = &rtcsdp.Session{
		URI:    nil,
		Title:  "",
		Timing: rtcsdp.Timing{},
		Medias: []*rtcsdp.Media{},
	}
	videoMedia := &rtcsdp.Media{
		Type:         rtcsdp.MediaTypeVideo,
		Direction:    rtcsdp.DirectionRecvOnly,
		SSRC:         123456,
		ReceiverSSRC: 0,
		OverTCP:      overTCP,
		MID:          "video",
		StreamId:     "stream_1",
		TrackId:      "track_1",
		CName:        "cname_1",
		StreamLabel:  "stream_label_1",
		Label:        "label_1",
		RTCPMux:      true,
		RTCPRsize:    true,
		Candidates:   nil,
		Formats: []format.Format{
			&format.H264{
				PayloadTyp: 106,
			},
		},
	}
	audioMedia := &rtcsdp.Media{
		Type:        rtcsdp.MediaTypeAudio,
		Direction:   rtcsdp.DirectionRecvOnly,
		SSRC:        123457,
		MID:         "audio",
		StreamId:    "stream_2",
		TrackId:     "track_2",
		CName:       "cname_2",
		StreamLabel: "stream_label_3",
		Label:       "label_3",
		RTCPMux:     true,
		RTCPRsize:   true,
		Candidates:  nil,
		Formats: []format.Format{
			&format.G711{
				MULaw: false,
			},
		},
	}

	_, _ = audioMedia, videoMedia

	offer.Medias = append(offer.Medias, videoMedia)

	return offer
}

func (tis *ObjectClient) run() {
	const (
		puId      = "UA_27423133"
		channelId = 0
	)

	var (
		objectOffer  *rtcsdp.Session
		objectAnswer *rtcsdp.Session
	)

	{
		// 构造请求
		objectOffer = tis.offer(overTCP)
		dataOffer, err := objectOffer.Marshal().Marshal()

		_ = dataOffer
		answerSDP := ""

		// 解析sdp
		objectAnswer, err = rtcsdp.Unmarshal([]byte(answerSDP))
		if err != nil {
			log.Println(err)
			return
		}

		// 兼容bvrtc
		for _, m := range objectAnswer.Medias {
			if m.Direction == rtcsdp.DirectionSendRecv || m.Direction == rtcsdp.DirectionSendOnly {
				m.SSRC, m.ReceiverSSRC = m.ReceiverSSRC, m.SSRC
			}
		}
	}

	session := rtcsession.NewClientSession(nil)
	session.OnOrderPacketRTP(tis.onPacket) // 接收包

	session.CreateOffer(objectOffer)
	session.SetRemoteAnswer(objectAnswer)

	_ = session.Open()
	_ = session.Wait()
}

var (
	decoder *rtph264.Decoder
	fp      *os.File
)

func (tis *ObjectClient) onPacket(value *rtcsession.OrderPacketRTP) {
	pkt := value.Packet

	if false {
		log.Printf("rtp %v %v pts: %12v ntp: %v  %v:%v  [%v]",
			pkt.SSRC,
			pkt.SequenceNumber,
			value.PTS,
			value.NTP,
			value.PtsOK,
			value.NtpOK,
			value.Receiver.Format().Codec(),
		)
	}

	if value.Receiver.Format().Codec() == "H264" {
		if decoder == nil {
			switch v := value.Receiver.Format().(type) {
			case *format.H264:
				decoder, _ = v.CreateDecoder()
			}
		}

		if decoder != nil {
			if fp == nil {
				fp, _ = os.Create("out.h264")
			}
			if nalus, err := decoder.Decode(pkt); err == nil {
				for _, nalu := range nalus {
					_ = nalu
					_, _ = fp.Write([]byte{0, 0, 0, 1})
					_, _ = fp.Write(nalu)
				}
			}
		}
	}
}

func main() {
	NewObjectClient().run()
}
